#include "UserGameLogsManager.h"
#include "StringConverter.h"
#include "ResourceManager.h"
#include "Database/DatabaseEnv.h"
#include "StringConverter.h"
#include "json/json.h"
#include "NGLog.h"
#include "Character.h"
#include "CharManager.h"
#include "Items.h"
#include "ItemManager.h"
#include "Users.h"
#include "UserManager.h"
#include "Channels.h"
#include "ChannelManager.h"
#include "Towns.h"
#include "TownManager.h"
#include "ItemModelManager.h"
#include "Message.h"
#include "CenterBankManager.h"
#include "VipCardManager.h"
#include "Tools.h"
#include "XMLData.h"
#include "GameDefine.h"
#include XMLDATA_MGR_PATH
#include LOGIC_MGR_PATH
#include LOG_MGR_PATH
#include PROTOCOLS_MGR_PATH
#include "OpcodesEx.h"
#include "WorldPacket.h"
#include "AIInterface.h"
#include "WSSocketManager.h"
#include "json/json.h"
#include "ProtocolDealEnums.h"
#include "url.h"
#include "showip.h"


//=============================游戏记录数据库相关操作===================================
bool UserGameLogManager::AddUserGameLog(UserGameLog & log)
{
	Fields fields;
	// sDataMgr.initData(DataManager::DatabaseTypeCenter, DB_NAME_USERGAMELOGS, &fields);
	sDataMgr.initData(DataManager::DatabaseTypeInfo, DB_NAME_USERGAMELOGS, &fields);
	
	fields["group_id"] = sChannelMgr.getGroupID();
	fields["server_id"] = sChannelMgr.getServerID();
	fields["agent_id"] = log.agent_id;
	fields["gz_id"] = log.gz_id;
	fields["game_name"] = log.game_name;
	fields["status"] = log.status;
	fields["type"] = log.type;
	fields["sub_type"] = log.sub_type;
	fields["flag"] = log.flag;
	fields["platform_id"] = log.platform_id;
	fields["user_name"] = log.user_name;
	fields["user_nick"] = log.user_nick;
	fields["src_id"] = log.src_id;
	fields["src_type"] = log.src_type;
	fields["dest_id"] = log.dest_id;
	fields["dest_type"] = log.dest_type;
	fields["target_id"] = log.target_id;
	fields["target_type"] = log.target_type;
	fields["change_model_id"] = log.change_model_id;
	fields["change_num"] = log.change_num;
	fields["org_num"] = log.org_num;
	fields["end_num"] = log.end_num;
	fields["congeal_num"] = log.congeal_num;
	fields["town_id"] = log.town_id;
	fields["channel_id"] = log.channel_id;
	fields["last_ip"] = log.last_ip;
	fields["last_time"] = log.last_time;
	fields["data1"] = log.data1;
	fields["data2"] = log.data2;
	fields["data3"] = log.data3;
	fields["data4"] = log.data4;
	fields["data5"] = log.data5;
	fields["data6"] = log.data6;
	fields["data7"] = log.data7;
	fields["data8"] = log.data8;
	
	fields["udata1"] = log.udata1;
	fields["udata2"] = log.udata2;
	fields["udata3"] = log.udata3;
	fields["udata4"] = log.udata4;
	fields["udata5"] = log.udata5;
	fields["udata6"] = log.udata6;
	fields["udata7"] = log.udata7;
	fields["udata8"] = log.udata8;
	
	fields["ldata1"] = log.ldata1;
	fields["ldata2"] = log.ldata2;
	fields["ldata3"] = log.ldata3;
	fields["ldata4"] = log.ldata4;
	
	fields["ludata1"] = log.ludata1;
	fields["ludata2"] = log.ludata2;
	fields["ludata3"] = log.ludata3;
	fields["ludata4"] = log.ludata4;
	
	fields["fdata1"] = log.fdata1;
	fields["fdata2"] = log.fdata2;
	fields["fdata3"] = log.fdata3;
	fields["fdata4"] = log.fdata4;
	
	fields["sdata1"] = log.sdata1;
	fields["sdata2"] = log.sdata2;
	fields["sdata3"] = log.sdata3;
	fields["sdata4"] = log.sdata4;
	fields["sdata5"] = log.sdata5;
	fields["sdata6"] = log.sdata6;
	fields["sdata7"] = log.sdata7;
	fields["sdata8"] = log.sdata8;
	
	fields["user_data"] = log.user_data;
	fields["info"] = log.info;
	fields["create_time"] = sGLMgr.GetCurDateTime();
	
	// if (!sDataMgr.insertData(DataManager::DatabaseTypeCenter, DB_NAME_USERGAMELOGS, &fields))
	if (!sDataMgr.insertData(DataManager::DatabaseTypeInfo, DB_NAME_USERGAMELOGS, &fields))
		return false;
	
	log.log_id = fields["log_id"].GetUInt64();
	return true;
}


#define SQLBUFER_LEN 16384

bool UserGameLogManager::UpdateUserGameLog(Fields * fields, const char * QueryString, ...)
{
	char sql[SQLBUFER_LEN] = ""; 
	va_list vlist; 
	va_start(vlist, QueryString); 
	vsnprintf(sql, SQLBUFER_LEN, QueryString, vlist); 
	va_end(vlist);
	// int count = sDataMgr.updateDataQueryAffected(DataManager::DatabaseTypeCenter, DB_NAME_USERGAMELOGS, fields, sql);
	int count = sDataMgr.updateDataQueryAffected(DataManager::DatabaseTypeInfo, DB_NAME_USERGAMELOGS, fields, sql);
	return count > 0;
}

bool UserGameLogManager::GetUserGameLog(const uint64 &log_id, UserGameLog * log)
{
	assert (log);
	FieldRows rows;
	// sDataMgr.getDatas(DataManager::DatabaseTypeCenter, DB_NAME_USERGAMELOGS, &rows, "`log_id` = %u", log_id);
	sDataMgr.getDatas(DataManager::DatabaseTypeInfo, DB_NAME_USERGAMELOGS, &rows, "`log_id` = %u", log_id);
	if (rows.empty())
		return false;
	
	Fields fields = rows.front();
	
	log->log_id = fields["log_id"].GetUInt64(); 
	log->group_id = fields["group_id"].GetUInt32(); 
	log->server_id = fields["server_id"].GetUInt32(); 
	log->agent_id = fields["agent_id"].GetUInt32(); 
	log->gz_id = fields["gz_id"].GetUInt32(); 
	log->game_name = fields["game_name"].GetValue(); 
	log->status = fields["status"].GetUInt32(); 
	log->type = fields["type"].GetUInt32(); 
	log->sub_type = fields["sub_type"].GetUInt32(); 
	log->flag = fields["flag"].GetUInt32(); 
	log->platform_id = fields["platform_id"].GetUInt32(); 
	
	log->user_name = fields["user_name"].GetValue(); 
	log->user_nick = fields["user_nick"].GetValue(); 
	
	log->src_id = fields["src_id"].GetUInt32(); 
	log->src_type = fields["src_type"].GetUInt32(); 
	log->dest_id = fields["dest_id"].GetUInt32(); 
	log->dest_type = fields["dest_type"].GetUInt32(); 
	log->target_id = fields["target_id"].GetUInt32(); 
	log->target_type = fields["target_type"].GetUInt32(); 
	log->change_model_id = fields["change_model_id"].GetUInt32(); 
	log->change_num = fields["change_num"].GetInt32(); 
	log->org_num = fields["org_num"].GetUInt32(); 
	log->end_num = fields["end_num"].GetUInt32(); 
	log->congeal_num = fields["congeal_num"].GetUInt32(); 
	log->town_id = fields["town_id"].GetUInt32(); 
	log->channel_id = fields["channel_id"].GetUInt32(); 
	log->last_ip = fields["last_ip"].GetValue(); 
	log->last_time = fields["last_time"].GetUInt32(); 
	
	log->data1 = fields["data1"].GetInt32();
	log->data2 = fields["data2"].GetInt32();
	log->data3 = fields["data3"].GetInt32();
	log->data4 = fields["data4"].GetInt32();
	log->data5 = fields["data5"].GetInt32();
	log->data6 = fields["data6"].GetInt32();
	log->data7 = fields["data7"].GetInt32();
	log->data8 = fields["data8"].GetInt32();
	
	log->udata1 = fields["udata1"].GetUInt32();
	log->udata2 = fields["udata2"].GetUInt32();
	log->udata3 = fields["udata3"].GetUInt32();
	log->udata4 = fields["udata4"].GetUInt32();
	log->udata5 = fields["udata5"].GetUInt32();
	log->udata6 = fields["udata6"].GetUInt32();
	log->udata7 = fields["udata7"].GetUInt32();
	log->udata8 = fields["udata8"].GetUInt32();
	
	log->ldata1 = fields["ldata1"].GetInt64();
	log->ldata2 = fields["ldata2"].GetInt64();
	log->ldata3 = fields["ldata3"].GetInt64();
	log->ldata4 = fields["ldata4"].GetInt64();
	
	log->ludata1 = fields["ludata1"].GetUInt64();
	log->ludata2 = fields["ludata2"].GetUInt64();
	log->ludata3 = fields["ludata3"].GetUInt64();
	log->ludata4 = fields["ludata4"].GetUInt64();
	
	log->fdata1 = fields["fdata1"].GetFloat();
	log->fdata2 = fields["fdata2"].GetFloat();
	log->fdata3 = fields["fdata3"].GetFloat();
	log->fdata4 = fields["fdata4"].GetFloat();
	
	log->sdata1 = fields["sdata1"].GetValue();
	log->sdata2 = fields["sdata2"].GetValue();
	log->sdata3 = fields["sdata3"].GetValue();
	log->sdata4 = fields["sdata4"].GetValue();
	log->sdata5 = fields["sdata5"].GetValue();
	log->sdata6 = fields["sdata6"].GetValue();
	log->sdata7 = fields["sdata7"].GetValue();
	log->sdata8 = fields["sdata8"].GetValue();
	
	log->user_data = fields["user_data"].GetValue();
	log->info = fields["info"].GetValue();
	log->create_time = fields["create_time"].GetValue();
	return true;
}


uint32 UserGameLogManager::GetUserGameLogList(std::list<UserGameLog> * lstData, const char * query,...)
{
	va_list argp;
	va_start(argp, query);
	lstData->clear();
	FieldRows fieldRows;
	
	char sql[SQLBUFER_LEN] = ""; 
	va_list vlist; 
	va_start(vlist, query); 
	vsnprintf(sql, SQLBUFER_LEN, query, vlist); 
	va_end(vlist);
	
	// if (!sDataMgr.getDatas(DataManager::DatabaseTypeCenter, DB_NAME_USERGAMELOGS, &fieldRows, sql))
	if (!sDataMgr.getDatas(DataManager::DatabaseTypeInfo, DB_NAME_USERGAMELOGS, &fieldRows, sql))
		return 0;
	
	FieldRows::iterator iter, enditer = fieldRows.end();
	for (iter = fieldRows.begin(); iter != enditer; ++ iter)
	{
		UserGameLog log;
		Fields &fields = *iter;
		
		log.log_id = fields["log_id"].GetUInt64(); 
		log.group_id = fields["group_id"].GetUInt32(); 
		log.server_id = fields["server_id"].GetUInt32(); 
		log.agent_id = fields["agent_id"].GetUInt32(); 
		log.gz_id = fields["gz_id"].GetUInt32(); 
		log.game_name = fields["game_name"].GetValue(); 
		log.status = fields["status"].GetUInt32(); 
		log.type = fields["type"].GetUInt32(); 
		log.sub_type = fields["sub_type"].GetUInt32(); 
		log.flag = fields["flag"].GetUInt32(); 
		log.platform_id = fields["platform_id"].GetUInt32(); 
		
		log.user_name = fields["user_name"].GetValue(); 
		log.user_nick = fields["user_nick"].GetValue();
		
		log.src_id = fields["src_id"].GetUInt32(); 
		log.src_type = fields["src_type"].GetUInt32(); 
		log.dest_id = fields["dest_id"].GetUInt32(); 
		log.dest_type = fields["dest_type"].GetUInt32(); 
		log.target_id = fields["target_id"].GetUInt32(); 
		log.target_type = fields["target_type"].GetUInt32(); 
		log.change_model_id = fields["change_model_id"].GetUInt32(); 
		log.change_num = fields["change_num"].GetInt32(); 
		log.org_num = fields["org_num"].GetUInt32(); 
		log.end_num = fields["end_num"].GetUInt32(); 
		log.congeal_num = fields["congeal_num"].GetUInt32(); 
		log.town_id = fields["town_id"].GetUInt32(); 
		log.channel_id = fields["channel_id"].GetUInt32(); 
		log.last_ip = fields["last_ip"].GetValue(); 
		log.last_time = fields["last_time"].GetUInt32(); 
		
		log.data1 = fields["data1"].GetInt32();
		log.data2 = fields["data2"].GetInt32();
		log.data3 = fields["data3"].GetInt32();
		log.data4 = fields["data4"].GetInt32();
		log.data5 = fields["data5"].GetInt32();
		log.data6 = fields["data6"].GetInt32();
		log.data7 = fields["data7"].GetInt32();
		log.data8 = fields["data8"].GetInt32();
		
		log.udata1 = fields["udata1"].GetUInt32();
		log.udata2 = fields["udata2"].GetUInt32();
		log.udata3 = fields["udata3"].GetUInt32();
		log.udata4 = fields["udata4"].GetUInt32();
		log.udata5 = fields["udata5"].GetUInt32();
		log.udata6 = fields["udata6"].GetUInt32();
		log.udata7 = fields["udata7"].GetUInt32();
		log.udata8 = fields["udata8"].GetUInt32();
		
		log.ldata1 = fields["ldata1"].GetInt64();
		log.ldata2 = fields["ldata2"].GetInt64();
		log.ldata3 = fields["ldata3"].GetInt64();
		log.ldata4 = fields["ldata4"].GetInt64();
		
		log.ludata1 = fields["ludata1"].GetUInt64();
		log.ludata2 = fields["ludata2"].GetUInt64();
		log.ludata3 = fields["ludata3"].GetUInt64();
		log.ludata4 = fields["ludata4"].GetUInt64();
		
		log.fdata1 = fields["fdata1"].GetFloat();
		log.fdata2 = fields["fdata2"].GetFloat();
		log.fdata3 = fields["fdata3"].GetFloat();
		log.fdata4 = fields["fdata4"].GetFloat();
		
		log.sdata1 = fields["sdata1"].GetValue();
		log.sdata2 = fields["sdata2"].GetValue();
		log.sdata3 = fields["sdata3"].GetValue();
		log.sdata4 = fields["sdata4"].GetValue();
		log.sdata5 = fields["sdata5"].GetValue();
		log.sdata6 = fields["sdata6"].GetValue();
		log.sdata7 = fields["sdata7"].GetValue();
		log.sdata8 = fields["sdata8"].GetValue();
		
		log.user_data = fields["user_data"].GetValue();
		log.info = fields["info"].GetValue();
		log.create_time = fields["create_time"].GetValue();
		
		lstData->push_back(log);
	}
	
	return lstData->size();
}

//=============================游戏记录数据库相关操作===================================

//==============================游戏记录逻辑相关操作====================================
// 登录退出游戏日志
bool UserGameLogManager::LoginOrLogoutGameLog(UserPtr & pUser, enLoginLogSubType login_type, String info)
{
	if(pUser.isNull())
		return false;
	
	UserGameLog log;
	log.type = enUserGameLogType_Login;		// 登录日志
	log.sub_type = login_type;				// 日志子类型（1 登录 2 退出）
	log.udata1 = sXmlDataMgr.GetConfXMLValue("MY_GAMEID");	// 游戏ID
	
	AppendUserInfo(log, pUser);
	AppendGameInfo(log, info);
	log.info = info;						// 日志内容
	return AddUserGameLog(log);
}

// 财富变化日志
bool UserGameLogManager::ItemsChangeLogWithUsers(stItemsChangeLog & parma)
{
	if(parma.pSrcUser.isNull() || parma.pDestUser.isNull())
		return false;
	
	UserGameLog log;
	log.type = enUserGameLogType_Item;		// 道具日志
	log.sub_type = parma.sub_type;			// 子类型
	
	log.change_model_id = parma.change_model_id;	// 改变道具模式ID
	log.change_num = parma.change_num;		// 改变数量
	log.org_num = parma.org_num;			// 改变前数量
	log.end_num = parma.end_num;			// 改变后数量
	log.congeal_num = parma.congeal_num;	// 改变后数量
	log.town_id = parma.town_id;			// 房间ID
	log.channel_id = parma.channel_id;		// 牌桌ID
	
	log.data2 = parma.change_num > 0 ? en_UNT_Add : en_UNT_Reduce;	// 变化类型（1 增加 2 减少）
	log.udata1 = sXmlDataMgr.GetConfXMLValue("MY_GAMEID");	// 游戏ID
	
	log.dest_id = parma.pDestUser->getUInt32Field("platform_id");	// 目标玩家PID
	log.dest_type = parma.pDestUser->getTargetType();				// 目标玩家类型
	log.sdata1 = parma.pDestUser->getStringField("nick");			// 目标玩家昵称
	
	String strTown = "";		// 房间名称
	TownPtr pTown = sTownMgr.getByHandle(parma.town_id);
	if(pTown.isNull())
		strTown = pTown->getStringField("name");
	
	char buf[256] = "";
	String strInfo = "";
	sprintf(buf, "玩家[%s]pid[%u]", parma.pSrcUser->getStringField("nick").c_str(), parma.pSrcUser->getUInt32Field("platform_id"));
	strInfo += buf;
	
	sprintf(buf, "在[%s]房间里牌桌ID为[%u]的牌桌上", strTown.c_str(), parma.channel_id);
	strInfo += buf;
	
	if(parma.change_num > 0)
		strInfo += "赢取";
	else if(parma.change_num == 0)
		strInfo += "平";
	else
		strInfo += "输给";
	
	sprintf(buf, "玩家[%s]pid[%u]", parma.pDestUser->getStringField("nick").c_str(), parma.pDestUser->getUInt32Field("platform_id"));
	strInfo += buf;
	
	String item_name = sGLMgr.GetItemName(parma.change_model_id);		// 道具名称
	sprintf(buf, "%sx%d", item_name.c_str(), abs(parma.change_num));
	strInfo += buf;
	
	AppendUserInfo(log, parma.pSrcUser);
	AppendGameInfo(log, strInfo);
	log.info = strInfo;
	return AddUserGameLog(log);
}

// 财富变化日志（系统）
bool UserGameLogManager::ItemsChangeLogWithSystem(stItemsChangeLog & parma)
{
	if(parma.pSrcUser.isNull())
		return false;
	
	UserGameLog log;
	log.type = enUserGameLogType_Item;				// 道具日志
	log.sub_type = parma.sub_type;					// 子类型
	
	log.change_model_id = parma.change_model_id;	// 改变道具模式ID
	log.change_num = parma.change_num;				// 改变数量
	log.org_num = parma.org_num;					// 改变前数量
	log.end_num = parma.end_num;					// 改变后数量
	log.congeal_num = parma.congeal_num;			// 冻结数量
	log.town_id = parma.town_id;					// 房间ID
	log.channel_id = parma.channel_id;				// 牌桌ID
	log.data7 = parma.extra_data1;					// 附加数据1
	log.data8 = parma.extra_data2;					// 附加数据2
	
	log.udata1 = sXmlDataMgr.GetConfXMLValue("MY_GAMEID");	// 游戏ID
	
	AppendUserInfo(log, parma.pSrcUser);
	AppendGameInfo(log, parma.info);
	log.info = parma.info;							// 日志内容
	return AddUserGameLog(log);
}

// 经验变化日志
bool UserGameLogManager::ExpsChangeLog(UserPtr & pUser, const uint8 & subType, const int32 & change_exps, String info)
{
	if(pUser.isNull())
		return false;
	
	CharPtr pChr = sCharMgr.getByHandle(pUser->getUInt32Field("char_id"));
	if(pChr.isNull())
		return false;
	
	UserGameLog log;
	log.type = enUserGameLogType_Exp;				// 经验日志
	
	log.change_num = change_exps;					// 改变的经验值
	log.end_num = pChr->getUInt32Field("exps");		// 修改后的经验值
	log.udata1 = sXmlDataMgr.GetConfXMLValue("MY_GAMEID");	// 游戏ID
	
	log.data1 = pChr->getUInt32Field("lv");			// 当前等级
	
	AppendUserInfo(log, pUser);
	AppendGameInfo(log, info);
	log.info = info;								// 日志内容
	return AddUserGameLog(log);
}

// 牌桌日志
bool UserGameLogManager::AboutTableLog(UserPtr & pUser, const uint32 & channelId, enTableLogSubType subType, String info)
{
	if(pUser.isNull())
		return false;
	
	UserGameLog log;
	log.type = enUserGameLogType_Table;		// 牌桌类型
	log.sub_type = subType;					// 子类型（进，出，返回，完成）
	log.dest_id = channelId;				// 牌桌ID
	log.dest_type = ResourceTypeChannel;	// 牌桌资源类型
	log.udata1 = sXmlDataMgr.GetConfXMLValue("MY_GAMEID");	// 游戏ID
	
	AppendUserInfo(log, pUser);
	AppendGameInfo(log, info);
	log.info = info;
	
	return AddUserGameLog(log);
}

// 实物兑换日志
bool UserGameLogManager::ChangePracticalityLog(const uint32 userId, const uint32 goodsId, const String &name, const uint32 number, const uint32 cost, const char *billId)
{
	
	return false;
}

// 元宝更新日志
bool UserGameLogManager::UpdateGoldsFromGatewayLog(stGoldsChangeLog parma)
{
	if(parma.pSrcUser.isNull())
		return false;

	UserGameLog log;
	log.type = enUserGameLogType_Gold;		// 元宝日志
	log.sub_type = parma.sub_type;			// 子类型
	
	log.change_model_id = parma.change_model_id;	// 改变道具模式ID
	log.change_num = parma.change_num;				// 改变数量
	log.org_num = parma.org_num;					// 改变前数量
	log.end_num = parma.end_num;					// 改变后数量
	
	log.udata1 = sXmlDataMgr.GetConfXMLValue("MY_GAMEID");	// 游戏ID
	
	AppendUserInfo(log, parma.pSrcUser);
	AppendGameInfo(log, parma.info);
	log.info = parma.info;
	
	return AddUserGameLog(log);
}

// 改变形象日志
bool UserGameLogManager::ChangeFiguralLog(UserPtr & pUser, const uint8 sourceType, const uint32 figuralId, const uint32 fromId, String info)
{
	if(pUser.isNull())
		return false;

	UserGameLog log;
	log.type = enUserGameLogType_Figural;	// 形象变化日志
	log.sub_type = sourceType;				// 子类型
	
	log.data1 = figuralId;					// 改变的形象ID
	log.data2 = fromId;						// 赠送的玩家ID
	log.udata1 = sXmlDataMgr.GetConfXMLValue("MY_GAMEID");	// 游戏ID
	
	AppendUserInfo(log, pUser);
	AppendGameInfo(log, info);
	log.info = info;						// 日志内容
	
	return AddUserGameLog(log);
}

bool UserGameLogManager::SystemTaxationLog(const uint32 townId, const uint32 channelId, const uint32 ante, const uint32 multy, const uint32 taxation, const uint8 subType, String info)
{
	UserGameLog log;
	log.type = enUserGameLogType_System;
	log.sub_type = subType;
	
	log.change_num = ante;			// 抽水数量
	
	log.town_id = townId;			// 房间ID
	log.channel_id = channelId;		// 牌桌ID
	log.data1 = taxation;			// 抽水
	log.data2 = multy;				// 倍数
	log.udata1 = sXmlDataMgr.GetConfXMLValue("MY_GAMEID");	// 游戏ID
	
	AppendGameInfo(log, info);
	log.info = info;
	
	return AddUserGameLog(log);
}

// 牌型日志
bool UserGameLogManager::GameCardsType(UserPtr & pUser, const uint32 & townId, const uint32 & channelId, const uint32 & cardType, const uint32 & data1, const uint32 & data2, String strCardType, String strCardsList, 
														const uint32 & data3, const uint32 & data4)
{
	if(pUser.isNull())
		return false;
	
	UserGameLog log;
	log.type = enUserGameLogType_CardsType;
	
	log.town_id = townId;			// 房间ID
	log.channel_id = channelId;		// 牌桌ID
	log.dest_id = cardType;			// 牌型
	
	log.data1 = data1;				// 牌型附加数据1
	log.data2 = data2;				// 牌型附加数据2（可用于排序的牌型）
	log.data3 = data3;				// 附加数据3
	log.data4 = data4;				// 附加数据4
	log.udata1 = sXmlDataMgr.GetConfXMLValue("MY_GAMEID");	// 游戏ID
	
	log.sdata1 = strCardType;		// 牌型描述（用于后台显示用）
	log.sdata2 = strCardsList;		// 牌列表
	
	AppendUserInfo(log, pUser);		// 追加用户信息
	return AddUserGameLog(log);
}

// 组局日志
bool UserGameLogManager::CreateCenterBattleLog(stCenterBattleLog cbl)
{
	if(cbl.pUser.isNull())
		return false;
	
	UserGameLog log;
	AppendUserInfo(log, cbl.pUser);
	AppendGameInfo(log, cbl.info);
	
	log.type = enUserGameLogType_CenterBattle;
	log.target_id = cbl.cb_id;
	log.gz_id = cbl.gz_id;
	log.data1 = cbl.model_id;
	log.data2 = cbl.num;
	log.data3 = cbl.status;
	log.data4 = cbl.loop;
	log.data5 = cbl.isPlayAll;
	log.data6 = cbl.mode;
	log.data7 = cbl.game_id;
	log.udata1 = sXmlDataMgr.GetConfXMLValue("MY_GAMEID");
	log.info = cbl.info;
	
	return AddUserGameLog(log);
}

// 玩家组局输赢日志
bool UserGameLogManager::CenterBattleResultLog(stPlayerCBResultInfo pcb_info)
{
	if(pcb_info.pUser.isNull())
		return false;
	
	UserGameLog log;
	AppendUserInfo(log, pcb_info.pUser);		// 追加用户信息
	AppendGameInfo(log, pcb_info.info);
	log.type = enUserGameLogType_PlayerCenterBattleResult;	
	
	log.target_id = pcb_info.cb_id;							// 组局ID
	log.gz_id = pcb_info.gz_id;								// 分区ID
	log.change_num = pcb_info.winlose_score;				// 输赢积分
	log.data1 = pcb_info.loop;								// 游戏局数
	log.data2 = pcb_info.roomOwner;							// 房主（0 否 1 是）
	log.data3 = pcb_info.winlose_score;						// 输赢
	log.data4 = pcb_info.top_times;							// 封顶倍数
	log.data5 = pcb_info.isPlayAll;							// 完成所有局数
	log.data7 = pcb_info.game_id;							// 游戏ID
	log.data8 = pcb_info.finish_status;						// 完成状态
	log.udata1 = sXmlDataMgr.GetConfXMLValue("MY_GAMEID");	// 配置的游戏ID
	log.udata2 = pcb_info.mode;								// 游戏玩法
	log.sdata1 = pcb_info.strJoinCode;						// 房间验证码
	log.info = pcb_info.info;								// 日志内容
	
	return AddUserGameLog(log);
}

// 玩家组局详细输赢日志
bool UserGameLogManager::CreatePlayerCenterBattleWinloseLog(stPlayerCBWinloseLog pcbl)
{
	if(pcbl.pUser.isNull())
		return false;
	
	UserGameLog log;
	AppendUserInfo(log, pcbl.pUser);
	AppendGameInfo(log, pcbl.info);
	
	log.type = enUserGameLogType_PlayerCenterBattleWinlose;
	log.target_id = pcbl.cb_id;		// 组局ID
	log.gz_id = pcbl.gz_id;			// 分区ID
	log.data1 = pcbl.curr_loop;		// 当前局数
	log.data2 = pcbl.top_times;		// 封顶倍数
	log.data3 = pcbl.mode;			// 游戏玩法
	log.data4 = pcbl.extra_data1;	// 附加数据（牛牛填写的是牌型）
	log.data7 = pcbl.game_id;		// 游戏ID
	log.info = pcbl.info;			// 日志内容
	
	return AddUserGameLog(log);
}

bool UserGameLogManager::FruitGameResultLog(CharPtr & pChr, std::map<uint32, uint32> mapChipin,
											std::map<uint32, uint32> mapBounty,
											const int32 & winLose, const int32 & sys_winLose)
{
	if(pChr.isNull())
		return false;
	
	UserPtr pUser = sUserMgr.getByHandle(pChr->getUInt32Field("userid"));
	if(pUser.isNull())
		return false;
	
	UserGameLog log;
	AppendUserInfo(log, pUser);
	log.type = enUserGameLogType_Item;
	log.sub_type = en_ST_FruitAllPutGet;
	log.gz_id = pUser->getUInt32Field("gz_id");
	
	Json::Value val, valChip;
	Json::FastWriter w;
	
	uint8 index = 0;
	std::map<uint32, uint32>::iterator itB, eiB = mapBounty.end();
	for(itB = mapBounty.begin(); itB!=eiB; ++itB)
	{
		switch(index)
		{
		case 0:	// 第一奖励
			log.data1 = itB->first;
			log.data2 = itB->second;
			break;
		case 1:	// 第二奖励
			log.data3 = itB->first;
			log.data4 = itB->second;
			break;
		case 2:	// 第三奖励
			log.data5 = itB->first;
			log.data6 = itB->second;
			break;
		case 3:	// 第四奖励
			log.data7 = itB->first;
			log.data8 = itB->second;
			break;
		}
		
		Json::Value valB;
		valB[0] = itB->first;
		valB[1] = itB->second;
		
		val[index++] = valB;
	}
	
	log.sdata1 = w.write(val);
	
	log.change_num = winLose;										// 本局输赢
	log.end_num = sGLMgr.GetItemNum(pChr, ItemModel_Coins);			// 输赢后当前剩余
	log.ldata1 = sys_winLose;										// 系统总输赢
	
	std::map<uint32, uint32>::iterator itC, eiC = mapChipin.end();
	for(itC = mapChipin.begin(); itC!=eiC; ++itC)
	{// 下注详细
		uint32 chipin = itC->second;
		valChip[itC->first - 1] = chipin;
		
		switch(itC->first)
		{
		case 1:
			log.udata1 = chipin;		// 苹果
			break;
		case 2:
			log.udata2 = chipin;		// 橘子
			break;
		case 3:
			log.udata3 = chipin;		// 橄榄
			break;
		case 4:
			log.udata4 = chipin;		// 铃铛
			break;
		case 5:
			log.udata5 = chipin;		// 西瓜
			break;
		case 6:
			log.udata6 = chipin;		// 星星
			break;
		case 7:
			log.udata7 = chipin;		// 777
			break;
		case 8:
			log.udata8 = chipin;		// BEN
			break;
		}
	}
	
	log.sdata2 = w.write(valChip);		// 下注详情JSON版本
	
	
	return AddUserGameLog(log);
}

// 房间库存变化日志
bool UserGameLogManager::TownKuCunChangeLog(const uint32 & town_id,
											const int32 & change_num,
											const uint32 & curr_num,
											const uint8 & sub_type)
{
	UserGameLog log;
	log.type = enUserGameLogType_Item;
	log.sub_type = sub_type;
	
	log.src_id = town_id;
	log.src_type = RTT_TOWN;
	
	log.change_num = change_num;
	log.end_num = curr_num;
	
	return AddUserGameLog(log);
}

// 系统庄输赢日志
bool UserGameLogManager::SystemBankerWinLoseLog(const uint32 & town_id,
											const int32 & change_num,
											const uint32 & curr_num,
											const uint8 & sub_type)
{
	UserGameLog log;
	log.type = enUserGameLogType_Item;
	log.sub_type = sub_type;
	
	log.src_id = town_id;
	log.src_type = RTT_TOWN;
	
	log.change_num = change_num;
	log.end_num = curr_num;
	
	return AddUserGameLog(log);
}

//=============================游戏记录逻辑相关操作===================================
// 追加用户信息
bool UserGameLogManager::AppendUserInfo(UserGameLog & log, UserPtr & pUser)
{
	if(pUser.isNull())
		return false;
	
	String strIp = "";
	WSSocketPtr socket = pUser->m_Socket.getResourcePtr();
	if(!socket.isNull())
		strIp = socket->GetIP();
	
	log.last_ip = strIp;								// IP地址
	uint32 gz_id = pUser->getUInt32Field("gz_id");
	log.gz_id = gz_id;
	log.agent_id = pUser->getUInt32Field("reg_from");
	log.src_id =pUser->getUInt32Field("platform_id");
	log.src_type = pUser->getTargetType();
	log.platform_id = pUser->getUInt32Field("platform_id");
	log.user_name = pUser->getStringField("name");
	log.user_nick = pUser->getStringField("nick");
	log.flag = pUser->getUInt32Field("status");
	log.game_name = sXmlDataMgr.GetGameNameByGzID(gz_id);
	return true;
}

// 追加游戏名称和分区内容
void UserGameLogManager::AppendGameInfo(UserGameLog & log, String & info)
{
	String strGameInfo = "";
	char buf[256] = "";
	sprintf(buf, "游戏[%s]分区ID[%u]运营商ID[%u]", log.game_name.c_str(), log.gz_id, log.agent_id);
	
	strGameInfo += buf;
	strGameInfo += info;
	info = strGameInfo;
}

